/blog/

Consuming CLI globs with Clap in Rust

created: 2021-01-19T00:26:30Z
modified: 2021-01-19T03:51:36Z

This is just a little thing I ran into while building a CLI client for my custom CMS. What I wanted was a way to run a command on every markdown file in a given directory and have the client add a .content_meta file with the same name and a set of default value. It was pretty easy to handle, but not exactly documented clearly so here’s a blog post about it.

This is using the awesome Clap crate to handle CLI arguments. Clap has everything I needed, I just had to infer how some of it works from different use cases.

...
fn main() {
    let matches = App::new("cmscli")
        .version("0.1")
        .about("Command line interface to the CMS.")
        .author("Gatewaynode")
        .arg(
            Arg::with_name("make_meta")
                .short("m")
                .long("meta")
                .value_name("FILENAME")
                .help("Create a metadata file for a piece of content or directory")
                .takes_value(true)
                .multiple(true),
        )
        .get_matches();
    if matches.is_present("make_meta") {
        let filenames = matches.values_of("make_meta").unwrap();
        dbg!(&filenames);
        for filename in filenames {
            //do something with it here

The key here are the argument functions .takes_value(true) and .multiple(true). These change the input collected after the argument -m from a string to an iterable (probably a vec but that isn’t clear in the debug output).

$ app -m *.md
[src/main.rs:37] &filenames = Values {
    iter: Map {
        iter: Iter(
            [
                "Here\’s my page.md",
                "Old content goes here to die.md",
            ],
        ),
    },
}

This let’s me handle command line globs using * with a for each loop. And later, when it’s time to optimize, we can turn most for each loops into multithreaded operations with the equally awesome Rayon crate.

  • Creative Commons License
  • Author: Gatewaynode